import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文
# plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号
import math
import os
import glob

chinese = 'Source Han Serif CN'
filename = 'plotconfig.txt'
print("\n请修改配置文件" + filename + ",或者删除该文件重新生成！\r\n")
# 每个试样的属性数量
pn = 5
if not os.path.isfile(filename):
    # 试样数量
    snum = input("试样数量:")
    snum = 1 if not snum else int(snum)
    # 图片每行数量
    figlay = input("\r\n选择排列方式(每行的图数量):") if int(snum) > 1 else 1
    figlay = 1 if not figlay else int(figlay)
    # 数据来源
    num = 0
    files = []
    filen = []
    for file in glob.glob(r'*.xls*'):
        if "~" not in file:
            num += 1
            files.append(file)
    print("\r\n文件数量要与试样数量一致，同一来源请标多次！")
    for i in range(1, num + 1):
        print(str(i) + ":" + files[i - 1])
    filem = input("选择文件(两个文件用逗号隔开,默认1):")
    if not filem:
        filen.append("1")
    else:
        filen = filem.split(',')
    if len(filen) < snum:
        print("\r\n数据来源数量不对！退出程序！")
        os._exit(0)
    # print(files[int(filen[0])-1])

    # 索引名，即x轴名
    xindex = input('\r\nx轴单位(默认位置(mm)):')
    xindex = "位置(mm)" if not xindex else xindex
    # 设置y轴名称
    ylabel = input("\r\ny轴单位(默认HV0.2):")
    ylabel = "硬度(HV0.2)" if not ylabel else ylabel
    # 坐标轴范围
    initn = 4
    xfe = input('\r\nx轴范围(头尾用逗号隔开，默认自动):')
    xfe = 0 if not xfe else list(map(float, xfe.split(',')))
    initn += 1 if not xfe else initn
    yfe = input('\r\ny轴范围(头尾用逗号隔开，默认自动):')
    yfe = 0 if not yfe else list(map(float, yfe.split(',')))
    initn += 1 if not yfe else initn
    with open(filename, 'w+') as f:
        f.write("试样数量:" + str(snum))
        f.write("\r每行的图数量:" + str(figlay))
        f.write("\rx轴:" + xindex)
        f.write("\ry轴:" + ylabel)
        if xfe != 0:
            f.write("\rx轴范围:" + str(xfe)[1:-1])
        if yfe != 0:
            f.write("\ry轴范围:" + str(yfe)[1:-1])

    for i in range(1, snum + 1):
        sa = input("\r\n第" + str(i) + "个试样编号:")
        sa = "sample" + str(i) if not sa else sa
        # 数据列
        print("------x轴数据列在excel前列------")
        datat = input("第" + str(i) + "个图数据列(两列用逗号隔开，连续列则使用首尾列再用冒号隔开),默认A,B:")
        datat = "A,B" if not datat else datat
        # excel参数
        sheetn = input('请输入excel的表单序号，默认0,表示sheet1:')
        sheetn = 0 if not sheetn else int(sheetn)
        srows = input('请输入跳过的行数，默认0不跳行:')
        srows = 0 if not srows else int(srows)
        with open(filename, 'a+') as f:
            f.write("\r\n试样编号:" + sa)
            f.write("\r来源文件名(excel):" + files[int(filen[i - 1]) - 1])
            f.write("\r数据列:" + datat)
            f.write("\r表单号:" + str(sheetn))
            f.write("\r跳过行数:" + str(srows))

config = pd.read_csv('plotconfig.txt',
                     sep=':',
                     index_col=0,
                     header=None,
                     encoding='gbk')

listall = []
if '范围' in config.index[5]:
    initn = 6
elif '范围' in config.index[4]:
    initn = 5
else:
    initn = 4
# sheet_name=0表示读取sheet1数据，skiprows=2跳过前两行，header=None表示读取的第一行不作为列的名称
# index_col=0表示选取第一列作为行标签，usecols=[0,1]读取第一、二列数据,names设置每列的名字，包括索引列
# list的写法，小的数在前，index_col是指读进去后的第几列做为index,后边的names顺序与usecols对应
for i in range(0, int(config.iloc[0][1])):
    a = pd.read_excel(
        config.iloc[i * pn + initn + 1][1],
        engine="openpyxl",
        sheet_name=int(config.iloc[i * pn + initn + 3][1]),
        skiprows=int(config.iloc[i * pn + initn + 4][1]),
        header=None,
        usecols=config.iloc[i * pn + initn + 2][1],
        index_col=0,
        names=[config.iloc[2][1], config.iloc[i * pn + initn][1]])
    # 剔除索引或数据有NAN的行(实际就是不是我们的数据)，如果开头有类似数据的索引和数据行，请在读取时使用skiprows剔除
    a = a.loc[a.dropna().index.dropna()]
    listall.append(a)

# 数据对齐处理,并将图形对称到y轴附近
maxdata = []
xnscope = []
for i in range(len(listall)):
    data = listall[i]
    # 定义行数,0表示首行
    data['key'] = np.arange(len(data))
    # print(data.columns[0])
    # 创建一个dataframe
    data['pct'] = data[data.columns[0]].pct_change()
    # 计算波浪起止点，行数及对应的index
    xs = data[data.pct == data.pct.max()].key.values[0] - 1
    xsindex = data[data.key == xs].index
    xe = data[data.pct == data.pct.min()].key.values[0]
    xeindex = data[data.key == xe].index
    # print(xsindex,xeindex)
    # index操作时，完全对称居中，另一个程序是让其中一个点位于原点
    x0 = (sum(xeindex, xsindex) / 2)[0]  # 转换成numerical，供后面的广播减法
    # print(x0)
    xnscope.append((xsindex - x0, xeindex - x0))
    # print(x0)
    # 去除pct_change、key列，方便后面作图
    data.drop(['pct', 'key'], axis=1, inplace=True)
    listall[i] = data.set_index(data.index - x0)
    # 最大值定位
    ymax = listall[i].max()[0]
    yindex = listall[i][listall[i][listall[i].columns[0]] == ymax].index[0]
    maxdata.append([yindex, ymax])

fig = plt.figure(figsize=(14, 7))
figlay = int(config.iloc[1][1])
figrow = math.ceil(int(config.iloc[0][1]) / figlay)
ax = []
color = [
    '#4f81bd', '#c0504d', '#9bbb59', '#8064a2', '#4bacc6', 'yellow', 'black',
    'red', 'orange', 'blue'
]
marker = [
    '.', ',', 's', 'o', 'v', '^', '<', '>', '1', '2', '3', '4', 'p', '*', 'h',
    'H', '+', 'x', 'D', 'd', '|', '_'
]
for i in range(len(listall)):
    ax.append(fig.add_subplot(figrow, figlay, i + 1))
    ax[i].plot(listall[i], color=color[i], marker=marker[i + 2])
    # 图例内容使用元组模式，并在元素后面加上逗号，避免显示不全,loc=1表示在右上角，无此参数则是自动
    ax[i].legend((listall[i].columns[0], ), loc=0, prop={"family": chinese})
    # # 限制坐标范围
    if '范围' in config.index[4]:
        xyin = config.iloc[4][1].split(',')
        xyin = list(map(float, xyin))
        if 'y轴' in config.index[5]:
            yin = config.iloc[5][1].split(',')
            yin = list(map(float, yin))
            plt.ylim(yin[0], yin[1])
        if 'x轴' in config.index[4]:
            plt.xlim(xyin[0], xyin[1])
        else:
            plt.ylim(xyin[0], xyin[1])
    # 刻度字体大小
    plt.tick_params(labelsize=8)
    # 多图时每幅图加标题
    # if len(listall)>1:
    # 	plt.title(config.iloc[i*pn+initn][1],fontproperties=chinese)
    # 	# plt.text(0.5,0,config.iloc[i*pn+initn][1],fontproperties=chinese)
    plt.xlabel(listall[i].index.name, fontproperties=chinese)
    plt.ylabel(config.iloc[3][1], fontproperties=chinese)
    # 打开次刻度
    ax[i].minorticks_on()
    # 网格线
    ax[i].grid(which='major', color='k', linestyle='-', linewidth=1, alpha=0.3)
    ax[i].grid(which='minor',
               color='gray',
               linestyle='--',
               linewidth=1,
               alpha=0.3)
    # # 注释相对注释点的位置
    # zs=input("\r\n第"+str(i+1)+"幅图注释位置相对于要注释点的坐标(非0)(默认+30,-30):")
    # zs=[+30,-30] if not zs else zs.split(',')
    # 注解最大值
    # ax[i].annotate(maxdata[i][1],
    #                xy=(maxdata[i][0], maxdata[i][1]),
    #                xytext=(float(zs[0]), float(zs[1])),
    #                textcoords='offset points',
    #                fontsize=8,
    #                arrowprops=dict(facecolor='black',
    #                                headwidth=4,
    #                                width=0.1,
    #                                alpha=0.7))
    # 画竖直线vlines(x,ymin.ymax),水平用hlines
    plt.vlines(xnscope[i][0],
               listall[i].min()[0],
               maxdata[i][1],
               color='red',
               linestyle='--')
    plt.vlines(xnscope[i][1],
               listall[i].min()[0],
               maxdata[i][1],
               color='red',
               linestyle='--')

# # 画最大值的水平线
# y=ymax+a.index*0
# plt.plot(y,color='pink',linestyle='--',alpha=1)
# # 获取当前axes
# ax=plt.gca()
# # 隐藏上面和右边的坐标轴
# ax.spines['right'].set_color('none')
# ax.spines['top'].set_color('none')
# 底部对齐，避免覆盖子标题
# plt.suptitle(title,verticalalignment="bottom",fontproperties=chinese)
# 调整图片间距，默认(左left，下bottom，右right，上top，水平间距wspace，竖直间距hspace)(0.125,0.1,0.9,0.9,0.2,0.2)
# plt.subplots_adjust(wspace=0.35,hspace=0.5)
plt.tight_layout()

fig.savefig(config.iloc[3][1] + "独立图.png", dpi=140,
            bbox_inches='tight')  # dpi越大图越清晰
# fig.savefig(title+"独立图.svg")
plt.show()

# 一些方法
# a.size #获取行数
# a.values[0][0] #获取第一行第一列数据
# a.index.values[0] #索引第一个的值
# a.columns[0] #第一列的列索引名
# 获取dataframe列构成ndarray,a['1#'].values[1:]
# 获取一个Series：  a['1#'][1：]
# dataframe添加列时，使用series添加，索引用原来的索引，series可以值得数量不足
# a['diff']=pd.Series((a['1#'].values[1:]-a['1#'].values[:-1])/(a.index[1]-a.index[0]),index=a.index[1:])

# xs=a.loc[abs(a['diff'])>100].index[0]-(a.index[1]-a.index[0])

# xe=a.loc[abs(a['diff'])>100].index[-1]
